package grape.workflow.rest.definition.mvc;

import grape.common.exception.ExceptionTools;
import grape.workflow.rest.common.mvc.BaseController;
import grape.workflow.rest.definition.SomeVersionForm;
import grape.workflow.rest.definition.mapper.ProcessDefinitionWebMapper;
import grape.workflow.rest.definition.vo.ProcessDefinitionVo;
import grape.workflow.rest.form.FormTypeHelper;
import grape.workflow.service.canstartprocess.api.ICanStartProcessService;
import grape.workflow.service.canstartprocess.po.CanStartProcess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.flowable.engine.FormService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by yangwei
 * Created at 2020/6/28 14:26
 */
@RestController
@RequestMapping("/workflow/definition")
@Api(tags = "流程定义相关接口")
public class ProcessDefinitionController extends BaseController {

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private ProcessDefinitionWebMapper processDefinitionWebMapper;
    @Autowired
    private FormService formService;

    @Autowired
    private FormTypeHelper formTypeVoHelper;
    @Autowired
    private ICanStartProcessService iCanStartProcessService;

    /**
     * 流程定义列表接口 默认查询最新版本，主要用于发起流程管理添加或更新下拉
     * @return
     */
    @ApiOperation("流程定义最新版本列表接口")
    @PreAuthorize("hasAuthority('definition:latest:list')")
    @GetMapping(value = "/latest/list")
    @ResponseStatus(HttpStatus.OK)
    public List<ProcessDefinitionVo> listLatest(){
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        List<ProcessDefinition> list = processDefinitionQuery.latestVersion().list();
        if (isEmpty(list)) {
            throw ExceptionTools.dataNotExistRE("数据不存在");
        }
        return list.stream().map(processDefinitionWebMapper::poToVo).collect(Collectors.toList());
    }

    /**
     * 主要用于启动流程
     * @param someVersionForm
     * @return
     */
    @ApiOperation("获取流程定义某个版本接口")
    @PreAuthorize("hasAuthority('definition:someVersion')")
    @GetMapping(value = "/someVersion")
    @ResponseStatus(HttpStatus.OK)
    public ProcessDefinitionVo someVersion(SomeVersionForm someVersionForm){

        if (!isStrEmpty(someVersionForm.getCanStartProcessId())) {
            CanStartProcess canStartProcess = iCanStartProcessService.getById(someVersionForm.getCanStartProcessId());
            someVersionForm.setIsUseLatestVersion(canStartProcess.getIsUseLatestVersion());
            someVersionForm.setProcessDefinitionKey(canStartProcess.getProcessDefinitionKey());
            someVersionForm.setIsUseLatestVersion(canStartProcess.getIsUseLatestVersion());

        }

        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        processDefinitionQuery.processDefinitionKey(someVersionForm.getProcessDefinitionKey());

        if (someVersionForm.getIsUseLatestVersion() != null && someVersionForm.getIsUseLatestVersion()) {
            processDefinitionQuery.latestVersion();
        }else {
            processDefinitionQuery.processDefinitionVersion(someVersionForm.getProcessDefinitionVersion());
        }
        ProcessDefinition definition = processDefinitionQuery.singleResult();

        if (definition == null) {
            throw ExceptionTools.dataNotExistRE("数据不存在");
        }
        ProcessDefinitionVo processDefinitionVo = processDefinitionWebMapper.poToVo(definition);
        processDefinitionVo.setStartFormType(formTypeVoHelper.getStartFormTypeVo(definition));
        if (isStrEmpty(processDefinitionVo.getStartFormKey()) && processDefinitionVo.getStartFormType() != null) {
            processDefinitionVo.setStartFormKey(processDefinitionVo.getStartFormType().getFormKey());
        }
        return processDefinitionVo;
    }
}
